var cloudData = require('cloudUrl');
const MAX_V = 1500;// 果冻最大线性速度
const ADD_V = 500;// 碰撞table正面时获得的线性速度

const MAX_LEN = 500;// 平台最大长度
const MIN_LEN = 80;// 平台最小长度

const INIT_DOWN = 50;// 组件最低下降速度
const MAX_DOWN = 800;// 组件下降速度上限

const LAND_Y = -1500;// 初始陆地距果冻高度
const WALL_X = 1000;// 初始墙壁距果冻宽度

const MAX_ENG = 1000;// 能量值上限
const REC_ENG = 10;// 每0.1秒恢复能量值

const PROP_PROB = 0.2;// 道具每秒产率(0-1)

const BAR_DIST = 4;// 障碍物密集度
const BAR_HEIG = 2;// 开始生成障碍物的高度(BAR_HEIG*winSize.height)

const SPEED_CD = 10000;// 速度道具持续时间
cc.Class({
    extends: cc.Component,

    properties: {
        isDebug: false,
    	camera: cc.Node,
        tablePrefab: cc.Prefab,
    	propPrefab: cc.Prefab,
        yellowBarrierPrefab: cc.Prefab,
        redBarrierPrefab: cc.Prefab,
        jellyBarrierPrefab: cc.Prefab,
        tableList: cc.Node,
        propList: cc.Node,
    	barrierList: cc.Node,
        jelly: cc.Node,
        land: cc.Node,
        leftWall: cc.Node,
        rightWall: cc.Node,
        energyBar: cc.Node,
        settlementScore: cc.Label,
        settlementHeight: cc.Label,
        settlementChipLayout: cc.Node,
        chipFramePrefab: cc.Prefab
    },
    onLoad () {
        // 平台最大长度
        this.maxLen = MAX_LEN;
        // 平台最小长度
        this.minLen = MIN_LEN;
        // 最低下降速度
        this.minDown = INIT_DOWN;
        // 果冻最大线性速度
        this.maxV = MAX_V;
        // 碰撞table正面时获得的线性速度
        this.addV = ADD_V;
        // 储存已创建的table节点
        this.tableL = [];
        // 获取能量条组件
        this.energy = this.energyBar.getComponent(cc.ProgressBar);
        // 设置能量值上限
        this.maxEng = MAX_ENG;
        // 设置速度道具持续时间
        this.maxSpeedCD = SPEED_CD;
        // 初始化游戏
        this.initGame();
    },
    start(){
        if(CC_WECHATGAME){
            // 播放背景音乐
            var audios = cc.director.getScene().getChildByName('audios').getComponent('audios');
            audios.changeBgm(audios.bgm3);
        }
    },
    update(){
        // 限制果冻最大线性速度
        let rigidBody = this.jelly.getComponent(cc.RigidBody);
        let v = Math.sqrt(Math.pow(rigidBody.linearVelocity.x,2)+Math.pow(rigidBody.linearVelocity.y,2));
        if(v>this.maxV){
            rigidBody.linearVelocity = cc.v2(rigidBody.linearVelocity.x*this.maxV/v,rigidBody.linearVelocity.y*this.maxV/v);
        }
    	// 更新触摸未释放时的table位置（相对屏幕保持不变）
		if(this.newTable){
			this.newTable.setPosition(cc.v2(this.jelly.x+this.startX,this.jelly.y+this.startY));
		}
        // 当table没入地面时销毁节点
        for(let i=0;i<this.tableL.length;i++){
            if(this.tableL[i].y<this.land.y-this.maxLen){
                this.tableL[i].destroy();
                this.tableL.splice(i,1);
                i--;
            }
        }
        // 速度道具持续时间
        cc.find('Canvas/ui/speedBuff').active = Boolean(this.speedCD);
        cc.find('Canvas/ui/speedBuff/speedBuff').getComponent(cc.Sprite).fillRange = this.speedCD/this.maxSpeedCD-1;
        // 果冻杯数量
        cc.find('Canvas/ui/jellyBarrierNum/Label').getComponent(cc.Label).string = String(this.jellyBarrierNum);
        // 当前高度
        this.currentHeight = (this.jelly.y-this.land.y-this.jelly.height/2)/100;
        cc.find('Canvas/ui/currentHeight/Label').getComponent(cc.Label).string = String(Math.floor(this.currentHeight));
        // 历史高度
        this.recordHeight = Math.max(this.currentHeight,this.recordHeight);
        cc.find('Canvas/ui/recordHeight/Label').getComponent(cc.Label).string = String(Math.floor(this.recordHeight));
        // 历史分数
        cc.find('Canvas/ui/score/Label').getComponent(cc.Label).string = String(this.recordScore);
        // 创建障碍物
        this.createBarrier();
	},
    /**
     * 初始化游戏
     */
    initGame(){
        // 启用物理系统
        cc.director.getPhysicsManager().enabled = true;
        if(this.isDebug){ // 开启调试信息
            var draw = cc.PhysicsManager.DrawBits;
            cc.director.getPhysicsManager().debugDrawFlags = draw.e_shapeBit|draw.e_jointBit;
        }
        // 当前组件下降速度初始化
        this.currentDown = this.minDown;
        // 创建初始table
        let initTable = cc.instantiate(this.tablePrefab);
        // 初始table位置
        initTable.setPosition(cc.v2(-initTable.width/2,-400));
        initTable.color = cc.color(255,255,255);
        // 初始table下降速度
        initTable.getComponent(cc.RigidBody).linearVelocity = cc.v2(0,-this.currentDown);
        // 启动table下沉
        initTable.getComponent(cc.RigidBody).type = 1;
        // 关闭碰撞监听
        initTable.getComponent(cc.RigidBody).enabledContactListener = false;
        // 启动物理碰撞
        initTable.getComponents(cc.PhysicsBoxCollider)[0].sensor = false;
        initTable.getComponents(cc.PhysicsBoxCollider)[1].sensor = false;
        // 更改碰撞标记
        initTable.getComponents(cc.PhysicsBoxCollider)[0].tag = 2;
        initTable.getComponents(cc.PhysicsBoxCollider)[1].tag = 3;
        // 添加table节点
        this.tableList.addChild(initTable);
        this.tableL.push(initTable);

        // 果冻复位
        this.jelly.x = 0;
        this.jelly.y = 0;
        this.jelly.angle = 0;
        // 果冻初始线性、角速度
        this.jelly.getComponent(cc.RigidBody).linearVelocity = cc.v2(0,-300);
        this.jelly.getComponent(cc.RigidBody).angularVelocity = 0;

        // 设置初始陆地距果冻高度
        this.land.y = LAND_Y;
        // 设置初始墙壁距果冻宽度
        this.leftWall.x = -WALL_X;
        this.rightWall.x = WALL_X;

        // 分数归零
        this.recordScore = 0;
        // 果冻杯数量归零
        this.jellyBarrierNum = 0;
        // CD归零
        this.speedCD = 0;
        // 历史高度
        this.recordHeight = 0;
        // 开启创建平台事件监听
        this.createTable();
        // 开启创建道具
        this.createProp();
        // 已创建障碍物的地图标记(从地面往上 barMap*屏幕高度 的位置不再生成障碍物)
        this.barMap = BAR_HEIG;
        // 组件下降速度每秒增加1
        this.mapDown();
        // 每0.5秒增加10分
        this.addScore();
        // 设置每0.1秒恢复能量值
        this.recoverEng(REC_ENG,100);
        // 设置当前能量值
        this.currentEng = this.maxEng;
        // 未复活标记
        this.resurgence = false;
    },
    
    /**
     * 暂停游戏
     */
    pauseGame(){
        if(!this.isPause){
            // 关闭物理系统
            cc.director.getPhysicsManager().enabled = false;
            // 关闭事件监听
            this.camera.off('touchstart');
            this.camera.off('touchmove');
            this.camera.off('touchend');
            // 停止能量值恢复
            clearInterval(this.engT);
            // 停止增加分数
            clearInterval(this.scoreT);
            // 停止创建道具
            clearInterval(this.propT);
            // 停止增加组件下降速度
            clearInterval(this.downT);
            this.isPause = true; 
            // 停止buffCD
            clearTimeout(this.jellySpeedT);
            clearInterval(this.speedPropCDT);
        }else{
            // 启用物理系统
            cc.director.getPhysicsManager().enabled = true;
            // 重启事件监听
            this.createTable();
            // 恢复能量值恢复
            this.recoverEng(REC_ENG,100);
            // 恢复增加分数
            this.addScore();
            // 恢复创建道具
            this.createProp();
            // 恢复增加组件下降速度
            this.mapDown();
            this.isPause = false;
            // 继续buff
            this.jellySpeedProp(this.speedCD)
      }
    },
    /**
     * 重置游戏
     */
    restartGame(){
        // 关闭物理系统
        cc.director.getPhysicsManager().enabled = false;
        // 关闭事件监听
        this.camera.off('touchstart');
        this.camera.off('touchmove');
        this.camera.off('touchend');
        // 停止能量值恢复
        clearInterval(this.engT);
        // 停止增加分数
        clearInterval(this.scoreT);
        // 停止创建道具
        clearInterval(this.propT);
        // 停止增加组件下降速度
        clearInterval(this.downT);
        // 停止buffCD
        clearTimeout(this.jellySpeedT);
        clearInterval(this.speedPropCDT);
        // 清空场景中的table
        this.tableList.removeAllChildren();
        // 清空场景中的prop
        this.propList.removeAllChildren();
        // 清空场景中的barrier
        this.barrierList.removeAllChildren();
        // 初始化游戏
        this.initGame();
        this.isPause = false;
    },
    /**
     * 结束游戏
     */
    endGame(){
        // 关闭物理系统
        cc.director.getPhysicsManager().enabled = false;
        // 关闭事件监听
        this.camera.off('touchstart');
        this.camera.off('touchmove');
        this.camera.off('touchend');
        // 停止能量值恢复
        clearInterval(this.engT);
        // 停止增加分数
        clearInterval(this.scoreT);
        // 停止创建道具
        clearInterval(this.propT);
        // 停止增加组件下降速度
        clearInterval(this.downT);
        // 停止buffCD
        clearTimeout(this.jellySpeedT);
        clearInterval(this.speedPropCDT);
        // 结算弹窗数据
        this.settlementScore.string = String(Math.floor(this.recordScore));
        this.settlementHeight.string = String(Math.floor(this.recordHeight));
    },
    /**
     * 复活游戏
     */
    resurgenceGame(){
        // 果冻复位
        this.jelly.x = 0;
        this.jelly.y = Math.max(0,this.currentHeight*100+this.jelly.height/2+this.land.y);
        this.jelly.angle = 0;
        // 果冻初始线性、角速度
        this.jelly.getComponent(cc.RigidBody).linearVelocity = cc.v2(0,-300);
        this.jelly.getComponent(cc.RigidBody).angularVelocity = 0;
        // 停止buffCD
        clearTimeout(this.jellySpeedT);
        clearInterval(this.speedPropCDT);
        // CD归零
        this.speedCD = 0;
        // 清空场景中的table
        this.tableList.removeAllChildren();
        // 清空场景中的prop
        this.propList.removeAllChildren();
        // 清空场景中的barrier
        this.barrierList.removeAllChildren();
        // 当前组件下降速度初始化
        this.currentDown = this.minDown;
        // 复活标记
        this.resurgence = true;
    },
	/**
	 * 启动事件监听创建table
	 */
	createTable(){
		this.camera.on('touchstart',(event)=>{
            // 若已存在newTable，销毁此节点
            if(this.newTable) this.newTable.destroy();
			// 获取点击位置
            this.startX = event.getLocation().x-cc.winSize.width/2;
            this.startY = event.getLocation().y-cc.winSize.height/2;
            this.endX = event.getLocation().x-cc.winSize.width/2;
            this.endY = event.getLocation().y-cc.winSize.height/2;
            // 创建table节点
            this.newTable = cc.instantiate(this.tablePrefab);
        	this.tableList.addChild(this.newTable);
            // 设置透明度
            this.newTable.opacity = 100;
            this.updateTable();
        });
        this.camera.on('touchmove',(event)=>{
        	// 获取点击位置
        	this.endX = event.getLocation().x-cc.winSize.width/2;
            this.endY = event.getLocation().y-cc.winSize.height/2;
            this.updateTable();
            // 超过最大最小长度、能量条不足、碰撞状态时table设为红色状态
            if(this.len<this.minLen||this.len>this.maxLen||this.len>this.currentEng||this.isContact===true){
                this.newTable.color = cc.color(255,0,0);
            }else{
                this.newTable.color = cc.color(255,255,255);
            }
        });
        this.camera.on('touchend',(event)=>{
            let tC = this.newTable.color;
            if((tC.r==255&&tC.g==0&&tC.b==0)||this.isContact){
                // 销毁红色状态或碰撞状态的table
                this.newTable.destroy();
            }else{
                // 更新能量值
                this.updateEng(-this.len);
                // table下降速度
                this.newTable.getComponent(cc.RigidBody).linearVelocity = cc.v2(0,-this.currentDown);
                // 启动table下沉
                this.newTable.getComponent(cc.RigidBody).type = 1;
                // 关闭碰撞监听
                this.newTable.getComponent(cc.RigidBody).enabledContactListener = false;
                // 启动物理碰撞
                this.newTable.getComponents(cc.PhysicsBoxCollider)[0].sensor = false;
                this.newTable.getComponents(cc.PhysicsBoxCollider)[1].sensor = false;
                // 更改碰撞标记
                this.newTable.getComponents(cc.PhysicsBoxCollider)[0].tag = 2;
                this.newTable.getComponents(cc.PhysicsBoxCollider)[1].tag = 3;
                // 更新物理组件
                this.newTable.getComponents(cc.PhysicsBoxCollider)[0].apply();
                this.newTable.getComponents(cc.PhysicsBoxCollider)[1].apply();
                // 设置透明度
                this.newTable.opacity = 255;
                // 储存已创建的table节点
                this.tableL.push(this.newTable);
            }
        	// 清除当前table记录
        	this.newTable = '';
        });
	},
	/**
	 * 更新触摸未释放时的table宽度、角度
	 */
	updateTable(){
		let detaX = this.startX-this.endX;
        let detaY = this.startY-this.endY;
        // 鼠标拖动距离
        this.len = Math.sqrt(Math.pow(detaX,2)+Math.pow(detaY,2));
         // 鼠标拖动角度
        let angle = detaY==0?(detaX<0?0:180):Math.atan(detaX/detaY)/Math.PI*180-90;
        // 设置table旋转角度
        if(detaY>0){
        	this.newTable.angle = -angle-180;
        }else{
        	this.newTable.angle = -angle;
        }
        // table物理组件
        let phy0 = this.newTable.getComponents(cc.PhysicsBoxCollider)[0];
        let phy1 = this.newTable.getComponents(cc.PhysicsBoxCollider)[1];
        if(detaX>0){
        	// table贴图倒置
        	this.newTable.scaleY = -1;
        	// 物理组件位置倒置
        	phy0.offset.y = -10;
        	phy1.offset.y = 10;
        }else{
        	this.newTable.scaleY = 1;
        	phy0.offset.y = 10;
        	phy1.offset.y = -10;
        }
        // 设置table宽度
        this.newTable.width = this.len;
        // 设置物理组件宽度及锚点
        phy0.size.width = this.len;
        phy0.offset.x = this.len/2;
        phy1.size.width = this.len;
        phy1.offset.x = this.len/2;
        // 更新物理组件
        phy0.apply();
        phy1.apply();
	},
    /**
     * 更新能量值
     */
    updateEng(num){
        this.currentEng = Math.max( Math.min(this.currentEng+num,this.maxEng) ,0);
        // 设置能量条组件进度
        this.energy.progress = this.currentEng/this.maxEng;
    },
    /**
     * 恢复能量值
     */
    recoverEng(rec,time){
        this.recEng = rec;
        this.engT = setInterval(()=>{
            this.updateEng(this.recEng);
            if(this.newTable){
                if(this.len>=this.minLen&&this.len<=this.maxLen&&this.len<=this.currentEng&&this.isContact===false){
                    // 当长度达标、能量条足够、非碰撞状态时取消红色状态
                    this.newTable.color = cc.color(255,255,255);
                }
            }
        },time);
    },
    /**
     * 创建道具
     */
    createProp(){
        this.propT = setInterval(()=>{
            //根据设置的道具产率PROP_PROB创建道具
            if(PROP_PROB!=0&&Math.floor(Math.random()*(1/PROP_PROB))==0){
                let prop = cc.instantiate(this.propPrefab);
                prop.x = Math.floor(Math.random()*(WALL_X*2+1)-WALL_X);
                prop.y = Math.floor(Math.random()*(cc.winSize.height+1)-cc.winSize.height/2)+this.jelly.y;
                // 随机道具
                var ranProp = Math.floor(Math.random()*4)
                prop.getComponent(cc.PhysicsPolygonCollider).tag = 40+ranProp;
                // 动态贴图
                if(CC_WECHATGAME){
                    switch(ranProp){
                        case 0:
                            // 积分道具
                            prop.getComponent(cc.Sprite).spriteFrame = new cc.SpriteFrame(cloudData.ccData.scoreProp);
                            break;
                        case 1:
                            // 能量道具
                            prop.getComponent(cc.Sprite).spriteFrame = new cc.SpriteFrame(cloudData.ccData.energyProp);
                            break;
                        case 2:
                            // 地图下降速度降低道具
                            prop.getComponent(cc.Sprite).spriteFrame = new cc.SpriteFrame(cloudData.ccData.mapUpProp);
                            break;
                        case 3:
                            // 果冻速度道具
                            prop.getComponent(cc.Sprite).spriteFrame = new cc.SpriteFrame(cloudData.ccData.speedProp);
                            break;
                    }
                }
                // 设置道具下降速度
                prop.getComponent(cc.RigidBody).linearVelocity = cc.v2(0,-this.currentDown);
                this.propList.addChild(prop);
            }
        },1000);
    },
    /**
     * 创建障碍物
     */
    createBarrier(){
        if (this.barMap<Math.floor(this.recordHeight*100/cc.winSize.height+2)){
            // 障碍物概率集
            let bPList = [this.jellyBarrierPrefab,this.yellowBarrierPrefab,this.yellowBarrierPrefab,this.yellowBarrierPrefab,this.redBarrierPrefab];
            // 每cc.winSize.height长的地图里随机创建0 - BAR_DIST个障碍物
            let ram = Math.floor(Math.random()*BAR_DIST);
            for(let i=0;i<ram;i++){
                var ranIndex = Math.floor(Math.random()*bPList.length);
                // 降低果冻杯产出
                if(ranIndex==0&&Math.random()<0.5) continue;
                let barrier = cc.instantiate(bPList[ranIndex]);
                barrier.x = Math.floor(Math.random()*(WALL_X*2+1)-WALL_X);
                barrier.y = Math.floor(Math.random()*(cc.winSize.height+1)+this.barMap*cc.winSize.height+LAND_Y);
                barrier.angle = Math.floor(Math.random()*90)-45;
                this.barrierList.addChild(barrier);
            }
            this.barMap += 1;//已创建障碍物的地图标记
        }
    },
    /**
     * 组件下降速度持续增加
     */
    mapDown(){
        this.downT = setInterval(()=>{
            // 下降速度每0.5秒增加1(最大值为MAX_DOWN)
            this.currentDown = Math.min(this.currentDown+1,MAX_DOWN);
            // 更新场景中所有平台的下降速度
            for(let i=0;i<this.tableL.length;i++){
                this.tableL[i].getComponent(cc.RigidBody).linearVelocity = cc.v2(0,-this.currentDown);
            }
            // 更新场景中所有道具的下降速度
            for(let j=0;j<this.propList.children.length;j++){
                this.propList.children[j].getComponent(cc.RigidBody).linearVelocity = cc.v2(0,-this.currentDown);
            }
        },500)
    },
    /**
     * 每0.5秒增加1分
     */
    addScore(){
        this.scoreT = setInterval(()=>{
            this.recordScore += 1;
        },500)
    },
    /**
     * 果冻速度道具
     */
    jellySpeedProp(time){
        if(time==0){
            // 恢复速度
            this.maxV = MAX_V;
            this.addV = ADD_V;
        }
        // 果冻最大线性速度+500
        this.maxV = MAX_V+500;
        // 碰撞table正面时获得的线性速度+200
        this.addV = ADD_V+200;
        // 重复触发重置cd
        clearTimeout(this.jellySpeedT);
        clearInterval(this.speedPropCDT);
        this.speedCD = time;
        // 实时更新cd
        this.speedPropCDT = setInterval(()=>{
            if(this.speedCD == 0){
                clearInterval(this.speedPropCDT)
            }else{
                this.speedCD = Math.max(this.speedCD-100,0)
            }
        },100);
        // 持续10秒
        this.jellySpeedT = setTimeout(()=>{
            // 恢复速度
            this.maxV = MAX_V;
            this.addV = ADD_V;
            console.log('恢复速度')
        },time)
    },
    /**
     * 上传数据
     */
    uploadData(){
        if(CC_WECHATGAME){
            // 上传高度
            wx.postMessage({
                msg: 'uploadHeight',
                height: String(Math.floor(this.recordHeight))
            });
            // 上传分数
            wx.postMessage({
                msg: 'uploadScore',
                score: String(Math.floor(this.recordScore))
            });
        }
    },
    /**
     * 获得碎片
     */
    getChip(){
        if(CC_WECHATGAME){
            if(this.jellyBarrierNum>0){
                wx.cloud.callFunction({
                    name:'getRamSkinChip',
                    data: {
                        chipNum: this.jellyBarrierNum
                    },
                    success: res=>{
                        console.log('获取碎片成功',res);
                        let chipList = res.result.ramChipList;
                        // 创建结算页面获取碎片内容
                        for(var i in chipList){
                            let chipFrame = cc.instantiate(this.chipFramePrefab);
                            chipFrame.getChildByName('chip').getComponent(cc.Sprite).spriteFrame = new cc.SpriteFrame(cloudData.ccData[chipList[i]]);
                            // 判断节点是否存在
                            if(cc.isValid(this.settlementChipLayout)) this.settlementChipLayout.addChild(chipFrame);
                        }
                    },
                    fail: err=>{
                        console.log('获取碎片失败',err);
                    }
                });
            }
        }
    },
    /**
     * 开关调试
     */
    changeDebug(){
        this.isDebug = !this.isDebug;
        if(this.isDebug){ // 开启调试信息
            // 设置调试绘制标志
            var draw = cc.PhysicsManager.DrawBits;
            // e_shapeBit绘制形状、e_aabbBit绘制包围盒、e_jointBit绘制关节链接信息
            cc.director.getPhysicsManager().debugDrawFlags = draw.e_shapeBit|draw.e_jointBit;
        }else{
            cc.director.getPhysicsManager().debugDrawFlags = 0;
        }
    }
});
